package edu.mtu.citizenscience.cs.sdk.uploader.upload.parts;

import java.io.File;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

import edu.mtu.citizenscience.cs.sdk.json.Request;
import edu.mtu.citizenscience.cs.sdk.json.Response;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderError;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderProgress;
import edu.mtu.citizenscience.cs.sdk.uploader.CitsciUploaderService;
import edu.mtu.citizenscience.cs.sdk.uploader.model.entry.FileEntry;
import edu.mtu.citizenscience.cs.sdk.uploader.model.entry.FileType;
import edu.mtu.citizenscience.cs.sdk.uploader.upload.UploadPart;
/**
 * @author Corbin Uselton <corbinu@cwuselto@mtu.edu>
 * @copyright (c) 2012 MichiganTech <http://www.mtu.edu>
 * @since 1.0
 * 
 * Uploads a Report File to the server
 */
public class ReportFile extends UploadPart {
	// the upload id
	private int uploadId;
	// the files report
	private Report report;
	// the file entry to upload
	private FileEntry file;
	
	/**
	 * @since 1.0
	 * 
	 * File Upload Request
	 */
	public static class FileRequest {
		// the file type
		private FileType type;
		// the file extension
		private String extension;
		
		/**
		 * Get the file 
		 * 
		 * @param   void
		 * @return	int - report id
		 */
		public FileType getType() 
		{
			return type;
		}
		
		/**
		 * Set the file type
		 * 
		 * @param   type - FileType - the type type
		 * @return	void
		 */
		public void setType(FileType type) 
		{
			this.type = type;
		}
		
		/**
		 * Get the file extension
		 * 
		 * @param   void
		 * @return	String - file extension
		 */
		public String getExtension() 
		{
			return extension;
		}
		
		/**
		 * Set the file extension
		 * 
		 * @param   extension - String - file extension
		 * @return	void
		 */
		public void setExtension(String extension) 
		{
			this.extension = extension;
		}
	}
	
	/**
	 * @since 1.0
	 * 
	 * File Upload Response payload
	 */
	public static class FileResponse {
		// path to the file on the server 
		private String path;

		/**
		 * Get the file server path
		 * 
		 * @param   void
		 * @return	String - path to the file on the server
		 */
		public String getPath() 
		{
			return path;
		}

		/**
		 * Set the file server path
		 * 
		 * @param   path - String - path to the file on the server
		 * @return	void
		 */
		public void setPath(String path) 
		{
			this.path = path;
		}
	}
	
	/**
	 * @since 1.0
	 * 
	 * File Upload Response payload
	 */
	private class FileResponseHandler extends UploadResponseHandler<FileResponse> {

		/**
		 * Create file response handler
		 * 
		 * @param   void
		 * @return	String - path to the file on the server
		 */
		public FileResponseHandler() 
		{
			super(FileResponse.class);
		}

		/**
		 * Called on response from the server
		 * 
		 * @param   response - Response<FileResponse> - the response from the server
		 * @return	void
		 */
		@Override
		public void response(Response<FileResponse> response) 
		{
			try 
			{
				// get the server file from the response and attach it to the file
				file.setServerPath(response.getPayload().getPath());
				
				// upload the next file on the report
				report.nextFile();
			}
			catch (JsonParseException e) 
			{
				e.printStackTrace();
				// if there is a problem parsing the response pass the error to the uploader
				uploader.sendError(CitsciUploaderError.INVALID_RESPONSE);
			}
			catch (JsonMappingException e) 
			{
				e.printStackTrace();
				// if there is a problem parsing the response pass the error to the uploader
				uploader.sendError(CitsciUploaderError.INVALID_RESPONSE);
			}
		}
	
	}
	
	/**
	 * Create a new Report File Upload Part
	 * 
	 * @param   uploader - CitsciUploaderService - the uploader service
	 * @param	uploadId - int - the upload id
	 * @param	report - the report upload part
	 * @param	file - FileEntry - the file entry to upload
	 * @return	void
	 */
	public ReportFile(CitsciUploaderService uploader, int uploadId, Report report, FileEntry file)
	{
		super(uploader);
		
		this.uploadId = uploadId;
		this.report = report;
		this.file = file;
	}
	
	/**
	 * Start the file upload
	 * 
	 * @param   reportNum - int - the report num
	 * @param	fileNum - int - the file num
	 * @return	void
	 */
	public void startUpload(int reportNum, int fileNum)
	{	
		// set the uploader progress to file and the report num and file num
		this.uploader.sendProgress(CitsciUploaderProgress.FILE, reportNum, fileNum);
		
		// new file request payload
		FileRequest payload = new FileRequest();
		// get the file extension and add it to the playload
		payload.setExtension(this.file.getValue().substring(this.file.getValue().lastIndexOf('.') + 1));
		// get the file type and add it to the playload
		payload.setType(this.file.getFileType());
		
		// create a new file request with the upload_file action, the upload id, and payload
		Request<FileRequest> request = new Request<FileRequest>("upload_file", this.uploadId, payload);
		// attach the file
		request.addParam("file", new File(this.file.getValue()));
		
		// send the request to the server passing the file response handler to handle the response
		this.uploader.doRequest(request, new FileResponseHandler());
	}
	
}